package com.service;

import static com.def.GenericDef.EVT_SCRP;
import static com.def.GenericDef.EVT_SCRP_CALCEL;
import static com.def.GenericDef.EXIST_CARRIER;
import static com.def.GenericDef.E_BIS_OPE;
import static com.def.GenericDef.E_READ_NOT_FOUND;
import static com.def.GenericDef.E_RET_BOX;
import static com.def.GenericDef.E_RET_PRD_INFO;
import static com.def.GenericDef.E_RET_PRD_SCRP;
import static com.def.GenericDef.E_RET_WO;
import static com.def.GenericDef.E_XPPRDSCRP_BOX_IS_EMPT;
import static com.def.GenericDef.E_XPPRDSCRP_BOX_NOT_EMPT;
import static com.def.GenericDef.E_XPPRDSCRP_INPUT_PRD_CNT_UNMATCH;
import static com.def.GenericDef.E_XPPRDSCRP_INVALID_BOX_PRD_CNT;
import static com.def.GenericDef.E_XPPRDSCRP_INVALID_BOX_STATUS;
import static com.def.GenericDef.E_XPPRDSCRP_INVALID_INPUT;
import static com.def.GenericDef.E_XPPRDSCRP_INVALID_PRD_STATUS;
import static com.def.GenericDef.E_XPPRDSCRP_INVALIED_UNSCRP_CNT;
import static com.def.GenericDef.E_XPPRDSCRP_WO_CNT_NOT_ENOUGH;
import static com.def.GenericDef.PROC_COMPLETE;
import static com.def.GenericDef.PROC_EMPTY;
import static com.def.GenericDef.PROC_SCRP;
import static com.def.GenericDef.PROC_WAIT;
import static com.def.GenericDef.RETURN_CODE_OK;
import static com.def.GenericDef.RETURN_CODE_SET_ERROR;
import static com.def.GenericDef.RETURN_CODE_UNKNOWN;
import static com.def.GenericDef.RETURN_MESG_OK;
import static com.def.GenericDef.TRX_OUT;
import static com.def.GenericDef.T_XPPRDSCRP;
import static com.def.GenericDef._NORMAL;
import static com.def.GenericDef._SPACE;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.LockMode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import com.dao.IBisOpeDao;
import com.dao.IRetBoxDao;
import com.dao.IRetPrdInfoDao;
import com.dao.IRetPrdScrpDao;
import com.dao.IRetWODao;
import com.icim.service.ICIMBaseService;
import com.model.Bis_ope;
import com.model.Bis_opeId;
import com.model.Ret_box;
import com.model.Ret_prd_info;
import com.model.Ret_prd_scrp;
import com.model.Ret_prd_scrpId;
import com.model.Ret_wo;
import com.rtnBean.NotFoundRtnBeen;
import com.rtnBean.SimpleRtnBeen;
import com.tx.xpprdscrp.XpprdscrpI;
import com.tx.xpprdscrp.XpprdscrpIA;
import com.tx.xpprdscrp.XpprdscrpO;
import com.tx.xpprdscrp.XpprdscrpOA;
import com.util.GUIDGenerator;
import com.util.MqOpe;
import com.util.Util;

@Scope("prototype")
@Service("XpprdscrpService")
public class XpprdscrpService extends ICIMBaseService{
	private static Logger logger = Logger.getLogger(XpprdscrpService.class);
	private static String TX_NAME = T_XPPRDSCRP;

	private XpprdscrpI inTrx;
	private XpprdscrpO outTrx;
	private MqOpe mqOpe;

	private String gszMsgBuf = "";
	private Timestamp gEvtTimestamp;
	private Double gEvtTimeD;
	private String gEvtSeqID;

	@Autowired
	private IRetBoxDao retBoxDao;
	@Autowired
	private IRetPrdInfoDao retPrdInfoDao;
	@Autowired
	private IRetPrdScrpDao retPrdScrpDao;
	@Autowired
	private IBisOpeDao bisOpeDao;
	@Autowired
	private IRetWODao retWODao;

	public String subMainProc(String strInMsg) {
		long rtnCode = _NORMAL;
		String outMsg = null;
		gszMsgBuf = "";
		gEvtTimestamp = Util.getCurrentTimestamp();
		gEvtTimeD = Util.getDoubleTime();
		gEvtSeqID = GUIDGenerator.javaGUID();

		inTrx = new XpprdscrpI();
		outTrx = new XpprdscrpO();
		outTrx.setTrx_id(TX_NAME);
		outTrx.setType_id(TRX_OUT);
		outTrx.setRtn_code(String.valueOf(RETURN_CODE_SET_ERROR));
		mqOpe = new MqOpe();

		try {
			inTrx = (XpprdscrpI) mqOpe.inStr2Obj(strInMsg, inTrx);
			logger.info("InTrx is " + strInMsg);

			rtnCode = subMainProc2(inTrx.getAction_flg().toCharArray()[0]);
			if (rtnCode != _NORMAL) {
				TransactionAspectSupport.currentTransactionStatus()
						.setRollbackOnly();
				outTrx.setRtn_code(String.valueOf(rtnCode));
				outTrx.setRtn_mesg(gszMsgBuf);
			} else {
				outTrx.setRtn_code(String.valueOf(RETURN_CODE_OK));
				outTrx.setRtn_mesg(RETURN_MESG_OK);
				retPrdInfoDao.flushCurSession();
			}
		} catch (Exception ex) {
			TransactionAspectSupport.currentTransactionStatus()
					.setRollbackOnly();
			outTrx.setRtn_mesg(ex.toString());
			outTrx.setRtn_code(RETURN_CODE_UNKNOWN);
			logger.error(Util.stackTraceToString(ex));
		} finally {
			outMsg = mqOpe.obj2Str(outTrx);
			return outMsg;
		}
	}

	private long subMainProc2(char actionType) {
		long lRc = _NORMAL;
		switch (actionType) {
		case 'S': {
			lRc = scrpFunc();
			break;
		}
		case 'R': {
			lRc = scrpCancelFunc();
			break;
		}
		case 'Q': {
			lRc = scrpQueryFunc();
			break;
		}
		default: {
			gszMsgBuf = "Invalide type input: [" + actionType + "]";
			return E_XPPRDSCRP_INVALID_INPUT;
		}
		}

		return lRc;
	}

	/**
	 * 检查输入数据
	 * 
	 * @return
	 */
	private long inputChk() {
		List<XpprdscrpIA> iary = inTrx.getIary();
		if (inTrx.getPrd_cnt() != iary.size()) {
			gszMsgBuf = "Input total prd count[" + inTrx.getPrd_cnt()
					+ "] unmatch with detail count[" + iary.size() + "]";
			return E_XPPRDSCRP_INPUT_PRD_CNT_UNMATCH;
		}
		return _NORMAL;
	}

	/**
	 * 同步WO的报废数量  & status
	 * 
	 * @param wo_id
	 * @param isScrp
	 * @param cnt
	 * @return
	 */
	private long syncWoScrpCnt(String wo_id, Boolean isScrp, int cnt) {
		SimpleRtnBeen rtn = new SimpleRtnBeen();
		long lRc = _NORMAL;
		Ret_wo ret_wo = new Ret_wo();
		ret_wo = retWODao.getWithLock(wo_id, LockMode.UPGRADE);
		if (null == ret_wo) {
			gszMsgBuf = new NotFoundRtnBeen(wo_id, Ret_wo.class).toString();
			return E_RET_WO + E_READ_NOT_FOUND;
		}

		if (isScrp) {
			ret_wo.setScrp_prd_qty(ret_wo.getScrp_prd_qty() + cnt);
			if (ret_wo.getScrp_prd_qty() + ret_wo.getWh_in_prd_qty() > ret_wo
					.getPln_prd_qty()) {
				gszMsgBuf = "内部订单[" + wo_id + "]计划数量["
						+ ret_wo.getPln_prd_qty() + "]，入库数量["
						+ ret_wo.getWh_in_prd_qty() + "]，报废数量不足！";
				return E_XPPRDSCRP_WO_CNT_NOT_ENOUGH;
			}
			rtn = retWODao.colseWo(ret_wo);
			if (rtn.getlRc() != _NORMAL) {
				return rtn.getlRc();
			}
			
		} else {
			ret_wo.setScrp_prd_qty(ret_wo.getScrp_prd_qty() - cnt);
			if (ret_wo.getScrp_prd_qty() < 0) {
				gszMsgBuf = "内部订单[" + wo_id + "]取消报废数量异常";
				return E_XPPRDSCRP_INVALIED_UNSCRP_CNT;
			}
			retWODao.update(ret_wo);
		}
		

		return lRc;
	}

	/**
	 * 取消报废(需要报废至一个空箱子中)
	 * 
	 * @return
	 */
	private long scrpCancelFunc() {
		long lRc = _NORMAL;
		lRc = inputChk();
		if (_NORMAL != lRc) {
			return lRc;
		}

		// Get cancel to box info
		Ret_box ret_box = new Ret_box();
		ret_box = retBoxDao.get(inTrx.getScrp_cancel_box());
		if (null == ret_box) {
			gszMsgBuf = new NotFoundRtnBeen(inTrx.getScrp_cancel_box(),
					Ret_box.class).toString();
			return E_RET_BOX + E_READ_NOT_FOUND;
		}

		// Check box status
		if (!PROC_EMPTY.equals(ret_box.getBox_stat())) {
			gszMsgBuf = "Box [" + ret_box.getBox_id() + "]'s status ["
					+ ret_box.getBox_stat() + "] is invalied, must ["
					+ PROC_EMPTY + "]!";
			return E_XPPRDSCRP_INVALID_BOX_STATUS;
		}

		// Check box real empty
		if (EXIST_CARRIER.equals(ret_box.getReal_emp())) {
			gszMsgBuf = "Box [" + ret_box.getBox_id() + "] not real EMPT!";
			return E_XPPRDSCRP_BOX_NOT_EMPT;
		}

		List<XpprdscrpIA> iary = inTrx.getIary();
		for (XpprdscrpIA item : iary) {
			// Get prd info
			Ret_prd_info prd = new Ret_prd_info();
			prd = retPrdInfoDao.get(item.getPrd_seq_id());
			if (null == prd) {
				gszMsgBuf = new NotFoundRtnBeen(item.getPrd_seq_id(),
						Ret_prd_info.class).toString();
				return E_RET_PRD_INFO + E_READ_NOT_FOUND;
			}

			// Check prd status
			if (!PROC_SCRP.equals(prd.getPrd_stat())) {
				gszMsgBuf = "Prd [" + prd.getPrd_seq_id() + "]'s status ["
						+ prd.getPrd_stat() + "] is invalied, must ["
						+ PROC_SCRP + "]!";
				return E_XPPRDSCRP_INVALID_PRD_STATUS;
			}

			// Cancel scrp
			prd.setBox_id_fk(inTrx.getScrp_cancel_box());
			prd.setPrd_stat(prd.getPv_prd_stat_fk());
			prd.setPv_prd_stat_fk(PROC_SCRP);
			prd.setEvt_seq_id(gEvtSeqID);
			prd.setEvt_timestamp(gEvtTimestamp);
			prd.setEvt_time_d(gEvtTimeD);
			prd.setEvt_usr(inTrx.getEvt_usr());
			prd.setEvt_cate(EVT_SCRP_CALCEL);
			prd.setSht_ope_msg(inTrx.getScrp_note());

			retPrdInfoDao.update(prd);

			lRc = syncWoScrpCnt(prd.getWo_id_fk(), false, 1);
			if (_NORMAL != lRc) {
				return lRc;
			}
			// Delete scrp record
			String hql = "FROM Ret_prd_scrp where id.prd_seq_id_fk = '"
					+ prd.getPrd_seq_id() + "'";
			Ret_prd_scrp ret_prd_scrp = new Ret_prd_scrp();

			ret_prd_scrp = (Ret_prd_scrp) retPrdScrpDao.comTblRead(hql);

			if (null == ret_prd_scrp) {
				gszMsgBuf = new NotFoundRtnBeen("prd_seq_id_fk = "
						+ prd.getPrd_seq_id(), Ret_prd_scrp.class).toString();
				return E_RET_PRD_SCRP + E_READ_NOT_FOUND;
			}
			retPrdScrpDao.delete(ret_prd_scrp);

		}

		// 更新box
		SimpleRtnBeen simpleRtnBeen = new SimpleRtnBeen(_NORMAL);
		simpleRtnBeen = retBoxDao.configBoxInfo(ret_box);
		if (_NORMAL != simpleRtnBeen.getlRc()) {
			gszMsgBuf = simpleRtnBeen.getMsgBuf();
			return simpleRtnBeen.getlRc();
		}

		ret_box = (Ret_box) simpleRtnBeen.getObj();
		retBoxDao.update(ret_box);

		return _NORMAL;
	}

	/**
	 * 报废
	 * 
	 * @return
	 */
	private long scrpFunc() {
		long lRc = _NORMAL;
		lRc = inputChk();
		if (_NORMAL != lRc) {
			return lRc;
		}

		List<XpprdscrpIA> iary = inTrx.getIary();

		for (XpprdscrpIA item : iary) {
			// Get prd info
			Ret_prd_info prd = new Ret_prd_info();
			prd = retPrdInfoDao.get(item.getPrd_seq_id());
			if (null == prd) {
				gszMsgBuf = new NotFoundRtnBeen(item.getPrd_seq_id(),
						Ret_prd_info.class).toString();
				return E_RET_PRD_INFO + E_READ_NOT_FOUND;
			}

			// Check prd status
			if (PROC_WAIT.equals(prd.getPrd_stat())
					|| PROC_COMPLETE.equals(prd.getPrd_stat())) {
				;
			} else {
				gszMsgBuf = "Prd [" + prd.getPrd_seq_id() + "]'s status ["
						+ prd.getPrd_stat() + "] is invalied, must ["
						+ PROC_WAIT + "]!";
				return E_XPPRDSCRP_INVALID_PRD_STATUS;
			}

			// Get box info
			Ret_box ret_box = new Ret_box();
			ret_box = retBoxDao.get(prd.getBox_id_fk());
			if (null == ret_box) {
				gszMsgBuf = new NotFoundRtnBeen(prd.getBox_id_fk(),
						Ret_box.class).toString();
				return E_RET_BOX + E_READ_NOT_FOUND;
			}

			// Check box status
			if (PROC_WAIT.equals(ret_box.getBox_stat())
					|| PROC_COMPLETE.equals(ret_box.getBox_stat())) {
				;
			} else {
				gszMsgBuf = "Box [" + ret_box.getBox_id() + "]'s status ["
						+ ret_box.getBox_stat() + "] is invalied!";
				return E_XPPRDSCRP_INVALID_BOX_STATUS;
			}

			// Check box real empty
			if (!EXIST_CARRIER.equals(ret_box.getReal_emp())) {
				gszMsgBuf = "Box [" + ret_box.getBox_id() + "] is EMPT!";
				return E_XPPRDSCRP_BOX_IS_EMPT;
			}

			// Real scrp
			prd.setPv_box_id_fk(prd.getBox_id_fk());
			prd.setBox_id_fk(_SPACE);
			prd.setPv_prd_stat_fk(prd.getPrd_stat());
			prd.setPrd_stat(PROC_SCRP);
			prd.setEvt_seq_id(gEvtSeqID);
			prd.setEvt_timestamp(gEvtTimestamp);
			prd.setEvt_time_d(gEvtTimeD);
			prd.setEvt_usr(inTrx.getEvt_usr());
			prd.setEvt_cate(EVT_SCRP);
			prd.setSht_ope_msg(inTrx.getScrp_note());

			retPrdInfoDao.update(prd);

			// Save scrp record
			Ret_prd_scrp ret_prd_scrp = new Ret_prd_scrp();
			Ret_prd_scrpId ret_prd_scrpId = new Ret_prd_scrpId();

			ret_prd_scrpId.setPrd_seq_id_fk(prd.getPrd_seq_id());
			ret_prd_scrpId.setEvt_seq_id_fk(gEvtSeqID);
			ret_prd_scrp.setId(ret_prd_scrpId);
			ret_prd_scrp.setPrd_stat(prd.getPrd_stat());
			ret_prd_scrp.setPv_prd_stat(prd.getPv_prd_stat_fk());
			ret_prd_scrp.setEvt_cate(prd.getEvt_cate());
			ret_prd_scrp.setEvt_usr(prd.getEvt_usr());
			ret_prd_scrp.setEvt_timestamp(prd.getEvt_timestamp());

			retPrdScrpDao.save(ret_prd_scrp);

			lRc = syncWoScrpCnt(prd.getWo_id_fk(), true, 1);
			if (_NORMAL != lRc) {
				return lRc;
			}

			// 更新box当前数量
			if (ret_box.getPrd_qty() > 0) {
				ret_box.setPrd_qty(ret_box.getPrd_qty() - 1);
				retBoxDao.update(ret_box);
			} else {
				gszMsgBuf = "Box [" + ret_box.getBox_id() + "]'s prd qty ["
						+ ret_box.getPrd_qty() + "] is invalied!";
				return E_XPPRDSCRP_INVALID_BOX_PRD_CNT;
			}

			// 数量降为0时置空box
			if (0 == ret_box.getPrd_qty()) {
				ret_box = retBoxDao.setBoxEmpt(ret_box);
				retBoxDao.update(ret_box);
			}
		}
		return _NORMAL;
	}

	/**
	 * Query all scrp pnl info
	 * 
	 * @return
	 */
	private long scrpQueryFunc() {
		long lRc = _NORMAL;

		List<Ret_prd_info> prdList = new ArrayList<Ret_prd_info>();
		List<XpprdscrpOA> oary = new ArrayList<XpprdscrpOA>();
		Bis_ope bis_ope = new Bis_ope();
		Bis_opeId bis_opeId = new Bis_opeId();

		String hqlQuery = "FROM Ret_prd_info where prd_stat= '" + PROC_SCRP
				+ "' ";
		prdList = retPrdInfoDao.find(hqlQuery);
		if (prdList.isEmpty()) {
			outTrx.setRtn_cnt(0);
		} else {
			outTrx.setRtn_cnt(prdList.size());
			for (Ret_prd_info prd : prdList) {
				XpprdscrpOA xpprdscrpOA = new XpprdscrpOA();
				xpprdscrpOA.setPrd_seq_id(prd.getPrd_seq_id());
				xpprdscrpOA.setLot_id(prd.getLot_id());
				xpprdscrpOA.setMdl_id_fk(prd.getMdl_id_fk());
				xpprdscrpOA.setWo_id_fk(prd.getWo_id_fk());
				xpprdscrpOA.setSo_id_fk(prd.getSo_id_fk());
				xpprdscrpOA.setPrd_stat(prd.getPrd_stat());
				xpprdscrpOA.setEvt_usr(prd.getEvt_usr());
				xpprdscrpOA.setEvt_timestamp(prd.getEvt_timestamp());
				
				bis_opeId.setOpe_id(prd.getCr_ope_id_fk());
				bis_opeId.setOpe_ver(prd.getCr_ope_ver_fk());
				bis_ope = bisOpeDao.get(bis_opeId);
				if (null == bis_ope) {
					gszMsgBuf = new NotFoundRtnBeen(bis_opeId.toString(),
							Bis_ope.class).toString();
					return E_BIS_OPE + E_READ_NOT_FOUND;
				}
				xpprdscrpOA.setScrp_ope(bis_ope.getOpe_dsc());

				oary.add(xpprdscrpOA);
			}
			outTrx.setOary(oary);
		}

		return _NORMAL;
	}

}
